package com.agh.portal.web;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.roo.addon.web.mvc.controller.finder.RooWebFinder;
import org.springframework.roo.addon.web.mvc.controller.scaffold.RooWebScaffold;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.agh.portal.data.DataComponent;
import com.agh.portal.domain.AghGroup;
import com.agh.portal.domain.GroupEvent;
import com.agh.portal.domain.Post;
import com.agh.portal.domain.Student;
import com.agh.portal.domain.util.SortTool;
import com.agh.portal.service.DataService;
import com.agh.portal.service.SecurityUtils;

@RequestMapping("/aghgroups")
@Controller
@RooWebScaffold(path = "aghgroups", formBackingObject = AghGroup.class)
@RooWebFinder
public class AghGroupController {
	
	@Autowired
	SecurityUtils secUtils;
	
	@Autowired
	MessageSource messageSource;
	
    @RequestMapping(produces = "text/html")
    public String list(
    		@RequestParam(value = "page", required = false) Integer page, 
    		@RequestParam(value = "size", required = false) Integer size, 
    		@RequestParam(value = "sortFieldName", required = false) String sortFieldName,
    		@RequestParam(value = "sortOrder" , required = false) String sortOrder,
    		Model uiModel) {
    	
    	List<AghGroup> aghGroups = AghGroup.findAllAghGroups();
    	
   		if(sortFieldName != null){
			SortTool sortTool = new SortTool();
			String sortProperty = (sortOrder!=null) ? sortFieldName+":"+sortOrder : sortFieldName;
		    aghGroups = (List<AghGroup>) sortTool.sort(aghGroups, sortProperty);
		    uiModel.addAttribute("sortFieldName", sortFieldName);
		    uiModel.addAttribute("sortOrder", sortOrder);
		}
    	
    	if(page!=null || size !=null){
            int sizeNo = size == null ? 10 : size.intValue();
            final int fromIndex = page == null ? 0 : (page.intValue() - 1) * sizeNo;
            int toIndex = fromIndex+sizeNo;
            if(fromIndex >= 0 && toIndex <= aghGroups.size() && fromIndex <= toIndex){
            	aghGroups = aghGroups.subList(fromIndex, toIndex);
            }
            uiModel.addAttribute("aghgroups", aghGroups);
            float nrOfPages = (float) AghGroup.countAghGroups() / sizeNo;
            uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages));
		}else {
            uiModel.addAttribute("aghgroups", aghGroups);
        }
        return "aghgroups/list";
    }
	
    
    @RequestMapping(value = "/{id}", produces = "text/html")
    public String show(
    		@PathVariable("id") Long id, 
    		@RequestParam(value = "responseMessage", required = false) String responseMessage,
    		@RequestParam(value = "alertType", required = false) String alertType,
    		Model uiModel) {
    	AghGroup aghGroup = AghGroup.findAghGroup(id);
    	
		List<DataComponent> latestContent = new ArrayList<DataComponent>();
    	latestContent.addAll(DataService.parsePostsToDataComponent(Post.findLatestPosts(4).getResultList()));
    	latestContent.addAll(DataService.parseGroupEventsToDataComponent(GroupEvent.findLatestGroupEvents(4).getResultList()));
    	DataService.sortByDateDesc(latestContent);

    	List<GroupEvent> events = new ArrayList<GroupEvent>();
    	events.addAll(aghGroup.getGroupEvents());
    	Collections.sort(events, new Comparator<GroupEvent>(){
    		public int compare(GroupEvent e1, GroupEvent e2){
    			return e2.getEventDate().compareTo(e1.getEventDate());
    		}
    	});
    	   
    	uiModel.addAttribute("responseMessage", responseMessage);
    	uiModel.addAttribute("alertType", alertType);
        uiModel.addAttribute("aghgroup", aghGroup);
        uiModel.addAttribute("contentList", latestContent);
        uiModel.addAttribute("events", events);
        uiModel.addAttribute("posts", aghGroup.getPosts());
        uiModel.addAttribute("students", aghGroup.getStudents());
        uiModel.addAttribute("invitedStudents", aghGroup.getInvitedStudents());
        uiModel.addAttribute("moderators", aghGroup.getModerators());
        uiModel.addAttribute("isModerator", aghGroup.getModerators().contains(secUtils.getLoggedStudent()));
        uiModel.addAttribute("isMember", aghGroup.getStudents().contains(secUtils.getLoggedStudent()));
        uiModel.addAttribute("isInvited", aghGroup.getInvitedStudents().contains(secUtils.getLoggedStudent()));
        uiModel.addAttribute("itemId", id);
        return "aghgroups/show";
    }
    
    //TODO: use hibernate search to create this finder
    @RequestMapping(value="find", produces = "text/html")
    public String find(
    		@RequestParam(value = "name", required = false) String name,
    		@RequestParam(value = "sortFieldName", required = false) String sortFieldName,
    		@RequestParam(value = "sortOrder" , required = false) String sortOrder
    		){
    	
    	return "aghgroups/list";
    }

	@RequestMapping(value = "/{id}", params = "requestInvite", produces = "text/html")
    public String requestInvite(@PathVariable("id") Long id, Model uiModel) {
		AghGroup aghGroup = AghGroup.findAghGroup(id);
		Student student = secUtils.getLoggedStudent();
		if(aghGroup == null || student == null || aghGroup.getInvitedStudents().contains(student) || aghGroup.getStudents().contains(student)){
			uiModel.addAttribute("responseMessage", messageSource.getMessage("action_unable_to_perform", null, LocaleContextHolder.getLocale()));
			uiModel.addAttribute("alertType", "danger");
			return "redirect:/aghgroups/"+id;
		}
		aghGroup.getInvitedStudents().add(student);
		aghGroup.persist();
		uiModel.addAttribute("responseMessage", messageSource.getMessage("action_invite_group_success", null, LocaleContextHolder.getLocale()));
    	
    	return "redirect:/aghgroups/"+id;
    }
	
	@RequestMapping(value = "/{id}", params = {"removeInvite", "studentId"}, produces = "text/html")
    public String removeInvite(
    		@PathVariable("id") Long id, 
    		@RequestParam(value = "studentId", required=true) Long studentId,
    		Model uiModel) {
		AghGroup aghGroup = AghGroup.findAghGroup(id);
		Student student = Student.findStudent(studentId);
		if(aghGroup == null || student == null || !aghGroup.getInvitedStudents().contains(student) || (!secUtils.isLoggedUserAndStudentMatch(student) && !aghGroup.getModerators().contains(secUtils.getLoggedStudent()))){
			uiModel.addAttribute("responseMessage", messageSource.getMessage("action_unable_to_perform", null, LocaleContextHolder.getLocale()));
			uiModel.addAttribute("alertType", "danger");
			return "redirect:/aghgroups/"+id;
		}
		aghGroup.getInvitedStudents().remove(student);
		aghGroup.persist();
		uiModel.addAttribute("responseMessage", messageSource.getMessage("action_leave_group_success", new Object[]{aghGroup.getName()}, LocaleContextHolder.getLocale()));
    	
    	return "redirect:/aghgroups/"+id;
    }
	
	@RequestMapping(value = "/{id}", params = {"acceptInvite", "studentId"}, produces = "text/html")
	public String acceptInvite(
			@PathVariable("id") Long id,  
			@RequestParam(value = "studentId", required=true) Long studentId,
			Model uiModel){
		AghGroup aghGroup = AghGroup.findAghGroup(id);
		Student student = Student.findStudent(studentId);
		
		if(aghGroup == null || student == null || !aghGroup.getInvitedStudents().contains(student) || !aghGroup.getModerators().contains(secUtils.getLoggedStudent())){
			uiModel.addAttribute("responseMessage", messageSource.getMessage("action_unable_to_perform", null, LocaleContextHolder.getLocale()));
			uiModel.addAttribute("alertType", "danger");
			return "redirect:/aghgroups/"+id;
		}
		
		aghGroup.getInvitedStudents().remove(student);
		aghGroup.getStudents().add(student);
		aghGroup.persist();
		uiModel.addAttribute("responseMessage", messageSource.getMessage("action_student_group_accepted", new Object[]{student.getName()+" "+student.getSurname(), aghGroup.getName()}, LocaleContextHolder.getLocale()));
		
		return "redirect:/aghgroups/"+id;
	}
	
	@RequestMapping(value = "/{id}", params = {"leaveGroup", "studentId"}, produces = "text/html")
    public String leaveGroup(
    		@PathVariable("id") Long id, 
			@RequestParam(value = "studentId", required=true) Long studentId,
			Model uiModel) {
		AghGroup aghGroup = AghGroup.findAghGroup(id);
		Student student = Student.findStudent(studentId);
		if(aghGroup == null || student == null || !aghGroup.getStudents().contains(student) || (!secUtils.isLoggedUserAndStudentMatch(student) && !aghGroup.getModerators().contains(secUtils.getLoggedStudent()))){
			uiModel.addAttribute("responseMessage", messageSource.getMessage("action_unable_to_perform", null, LocaleContextHolder.getLocale()));
			uiModel.addAttribute("alertType", "danger");
			return "redirect:/aghgroups/"+id;
		}
		
		aghGroup.getStudents().remove(student);
		aghGroup.getModerators().remove(student);
		aghGroup.persist();
		uiModel.addAttribute("responseMessage", messageSource.getMessage("action_leave_group_success", new Object[]{aghGroup.getName()}, LocaleContextHolder.getLocale()));
    	
    	return "redirect:/aghgroups/"+id;
    }
	
	@RequestMapping(value = "/{id}", params = {"addModerator", "studentId"}, produces = "text/html")
	public String addModerator(
			@PathVariable("id") Long id,  
			@RequestParam(value = "studentId", required=true) Long studentId,
			Model uiModel){
		AghGroup aghGroup = AghGroup.findAghGroup(id);
		Student student = Student.findStudent(studentId);
		
		if(aghGroup == null || student == null || !aghGroup.getStudents().contains(student) || aghGroup.getModerators().contains(student) || !aghGroup.getModerators().contains(secUtils.getLoggedStudent())){
			uiModel.addAttribute("responseMessage", messageSource.getMessage("action_unable_to_perform", null, LocaleContextHolder.getLocale()));
			uiModel.addAttribute("alertType", "danger");
			return "redirect:/aghgroups/"+id;
		}
		
		aghGroup.getModerators().add(student);
		aghGroup.persist();
		uiModel.addAttribute("responseMessage", messageSource.getMessage("action_student_priviliges_changed", new Object[]{student.getName()+" "+student.getSurname(), aghGroup.getName()}, LocaleContextHolder.getLocale()));
		
		return "redirect:/aghgroups/"+id;
	}
	
	@RequestMapping(value = "/{id}", params = "removeModerator", produces = "text/html")
    public String removeModerator(@PathVariable("id") Long id, Model uiModel) {
		AghGroup aghGroup = AghGroup.findAghGroup(id);
		Student student = secUtils.getLoggedStudent();
		if(aghGroup == null || student == null || !aghGroup.getModerators().contains(student)){
			uiModel.addAttribute("responseMessage", messageSource.getMessage("action_unable_to_perform", null, LocaleContextHolder.getLocale()));
			uiModel.addAttribute("alertType", "danger");
			return "redirect:/aghgroups/"+id;
		}
		
		aghGroup.getModerators().remove(student);
		aghGroup.persist();
		uiModel.addAttribute("responseMessage", messageSource.getMessage("action_student_priviliges_changed", new Object[]{student.getName()+" "+student.getSurname(), aghGroup.getName()}, LocaleContextHolder.getLocale()));
    	
    	return "redirect:/aghgroups/"+id;
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE, produces = "text/html")
    public String delete(@PathVariable("id") Long id, @RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
        AghGroup aghGroup = AghGroup.findAghGroup(id);
        aghGroup.remove();
        uiModel.asMap().clear();
        uiModel.addAttribute("page", (page == null) ? "1" : page.toString());
        uiModel.addAttribute("size", (size == null) ? "10" : size.toString());
        return "redirect:/aghgroups";
    }
}
